#include "tcpserverbase.h"

CTcpserverbase::CTcpserverbase(LPST_ENV_T pEnv, int nPort)
: m_pEnv(pEnv)
, m_pListener(NULL)
{
	m_nTimer.ev = NULL;
	if (m_pEnv->bNetworkReady){
		CreateServer(nPort);
	}
	else{
		m_nTimer.ev = evtimer_new(m_pEnv->pEvBase, CTcpserverbase::cbTimerTask, this);
		m_nTimer.tv.tv_sec = 1;
		m_nTimer.tv.tv_usec = 0;
		evtimer_add(m_nTimer.ev, &m_nTimer.tv);
	}
}

CTcpserverbase::~CTcpserverbase()
{
	CLEAR_EV(m_nTimer);
	
	if (m_pListener)
		evconnlistener_free(m_pListener);
	LOG4CPLUS_DEBUG(log_dsw, "Destroy tcp server!");
}

void CTcpserverbase::OnAcceptError(struct evconnlistener *listener)
{
	struct event_base *base = evconnlistener_get_base(listener);
	int err = EVUTIL_SOCKET_ERROR();
	LOG4CPLUS_ERROR(log_dsw, "Got an error on the listener!err = " << evutil_socket_error_to_string(err));
	void* pParam;
	pParam = (void*)m_pEnv;
	m_pEnv->pOnNotifyFunc(PMSG_SET_APPEXIT, pParam);
}

void CTcpserverbase::CreateServer(int nPort)
{
	LOG4CPLUS_DEBUG(log_dsw, "Create tcp server on port " << nPort);
	struct sockaddr_in sin;
	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = htonl(INADDR_ANY);
	sin.sin_port = htons(nPort);
	m_pListener = evconnlistener_new_bind(m_pEnv->pEvBase, CTcpserverbase::cb_OnAccept, this,
		LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE | LEV_OPT_THREADSAFE, -1, (struct sockaddr*)&sin, sizeof(sin));
	if (!m_pListener) {
		LOG4CPLUS_ERROR(log_dsw, "Couldn't create tcp server on port !" << nPort);
		return;
	}
	evconnlistener_set_error_cb(m_pListener, CTcpserverbase::cb_OnAcceptError);
}

void CTcpserverbase::OnTimer(int fd, short events)
{
	char sActiveIp[64];
	void* pParam;
	int nPort;
	if (!m_pEnv->bNetworkReady)
		goto WAIT_NETREADY;
	pParam = (void*)sActiveIp;
	if (m_pEnv->pOnNotifyFunc(PMSG_GET_ACTIVEIP, pParam) == 0){
		pParam = (void*)sActiveIp;
		m_pEnv->pOnNotifyFunc(PMSG_GET_VIDEOLISTEN_PORT, pParam);
		nPort = *((int*)pParam);
		CreateServer(nPort);
		return;
	}
WAIT_NETREADY:
	m_nTimer.tv.tv_sec = 5;
	evtimer_add(m_nTimer.ev, &m_nTimer.tv);
}

